#include "hex_parser.h"
#include <algorithm>
#include <cctype>

HexParser::HexParser() {
    file_info.total_records = 0;
    file_info.data_records = 0;
    file_info.total_data_bytes = 0;
    file_info.start_address = 0;
    file_info.end_address = 0;
    file_info.extended_linear_address = 0;
    file_info.extended_segment_address = 0;
}

HexParser::~HexParser() {
}

bool HexParser::parseFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "Error: Cannot open file " << filename << std::endl;
        return false;
    }
    
    file_info.filename = filename;
    file_info.records.clear();
    file_info.memory_map.clear();
    
    std::string line;
    uint32_t current_address = 0;
    uint32_t base_address = 0;
    
    while (std::getline(file, line)) {
        // 移除行尾的换行符和回车符
        line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
        line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
        
        // 跳过空行
        if (line.empty()) continue;
        
        // 检查是否以冒号开头
        if (line[0] != ':') {
            std::cerr << "Warning: Skipping invalid line: " << line << std::endl;
            continue;
        }
        
        HexRecord record = parseRecord(line);
        file_info.records.push_back(record);
        file_info.total_records++;
        
        if (!record.valid) {
            std::cerr << "Error: Invalid record: " << line << std::endl;
            continue;
        }
        
        // 处理不同类型的记录
        switch (record.type) {
            case HexRecordType::DATA: {
                file_info.data_records++;
                file_info.total_data_bytes += record.length;
                
                // 计算实际地址
                current_address = base_address + record.address;
                
                // 将数据添加到内存映射
                for (size_t i = 0; i < record.data.size(); ++i) {
                    file_info.memory_map[current_address + i] = record.data[i];
                }
                
                // 更新地址范围
                if (file_info.start_address == 0 || current_address < file_info.start_address) {
                    file_info.start_address = current_address;
                }
                if (current_address + record.length > file_info.end_address) {
                    file_info.end_address = current_address + record.length - 1;
                }
                break;
            }
            
            case HexRecordType::EXTENDED_LINEAR_ADDRESS: {
                if (record.data.size() >= 2) {
                    file_info.extended_linear_address = 
                        (static_cast<uint32_t>(record.data[0]) << 8) | record.data[1];
                    base_address = file_info.extended_linear_address << 16;
                }
                break;
            }
            
            case HexRecordType::EXTENDED_SEGMENT_ADDRESS: {
                if (record.data.size() >= 2) {
                    file_info.extended_segment_address = 
                        (static_cast<uint16_t>(record.data[0]) << 8) | record.data[1];
                    base_address = static_cast<uint32_t>(file_info.extended_segment_address) << 4;
                }
                break;
            }
            
            case HexRecordType::START_LINEAR_ADDRESS: {
                if (record.data.size() >= 4) {
                    file_info.start_address = 
                        (static_cast<uint32_t>(record.data[0]) << 24) |
                        (static_cast<uint32_t>(record.data[1]) << 16) |
                        (static_cast<uint32_t>(record.data[2]) << 8) |
                        record.data[3];
                }
                break;
            }
            
            case HexRecordType::END_OF_FILE: {
                std::cout << "End of file record detected" << std::endl;
                break;
            }
            
            default:
                break;
        }
    }
    
    file.close();
    return true;
}

bool HexParser::parseSingleRecord(const std::string& record) {
    // 清空之前的数据
    file_info.filename = "Single HEX Record";
    file_info.records.clear();
    file_info.memory_map.clear();
    file_info.segments.clear();
    file_info.total_records = 0;
    file_info.data_records = 0;
    file_info.total_data_bytes = 0;
    file_info.start_address = 0;
    file_info.end_address = 0;
    file_info.extended_linear_address = 0;
    file_info.extended_segment_address = 0;
    
    // 解析单行记录
    HexRecord parsed_record = parseRecord(record);
    file_info.records.push_back(parsed_record);
    file_info.total_records = 1;
    
    if (!parsed_record.valid) {
        std::cerr << "Error: Invalid HEX record format" << std::endl;
        return false;
    }
    
    // 处理记录类型
    switch (parsed_record.type) {
        case HexRecordType::DATA: {
            file_info.data_records = 1;
            file_info.total_data_bytes = parsed_record.length;
            
            // 将数据添加到内存映射
            for (size_t i = 0; i < parsed_record.data.size(); ++i) {
                file_info.memory_map[parsed_record.address + i] = parsed_record.data[i];
            }
            
            file_info.start_address = parsed_record.address;
            file_info.end_address = parsed_record.address + parsed_record.length - 1;
            break;
        }
        
        case HexRecordType::START_LINEAR_ADDRESS: {
            if (parsed_record.data.size() >= 4) {
                file_info.start_address = 
                    (static_cast<uint32_t>(parsed_record.data[0]) << 24) |
                    (static_cast<uint32_t>(parsed_record.data[1]) << 16) |
                    (static_cast<uint32_t>(parsed_record.data[2]) << 8) |
                    parsed_record.data[3];
            }
            break;
        }
        
        case HexRecordType::EXTENDED_LINEAR_ADDRESS: {
            if (parsed_record.data.size() >= 2) {
                file_info.extended_linear_address = 
                    (static_cast<uint32_t>(parsed_record.data[0]) << 8) | parsed_record.data[1];
            }
            break;
        }
        
        case HexRecordType::EXTENDED_SEGMENT_ADDRESS: {
            if (parsed_record.data.size() >= 2) {
                file_info.extended_segment_address = 
                    (static_cast<uint16_t>(parsed_record.data[0]) << 8) | parsed_record.data[1];
            }
            break;
        }
        
        default:
            break;
    }
    
    return true;
}

HexRecord HexParser::parseRecord(const std::string& line) {
    HexRecord record;
    record.valid = false;
    
    if (line.length() < 11 || line[0] != ':') {
        return record;
    }
    
    try {
        // 解析长度
        record.length = hexStringToNumber(line.substr(1, 2));
        
        // 解析地址
        record.address = static_cast<uint16_t>(hexStringToNumber(line.substr(3, 4)));
        
        // 解析记录类型
        uint8_t type_byte = static_cast<uint8_t>(hexStringToNumber(line.substr(7, 2)));
        record.type = static_cast<HexRecordType>(type_byte);
        
        // 解析数据
        size_t data_start = 9;
        size_t data_length = record.length * 2;
        if (line.length() < data_start + data_length + 2) {
            return record;
        }
        
        std::string data_str = line.substr(data_start, data_length);
        record.data = hexStringToBytes(data_str);
        
        // 解析校验和
        record.checksum = static_cast<uint8_t>(hexStringToNumber(line.substr(data_start + data_length, 2)));
        
        // 验证校验和
        record.valid = validateChecksum(record);
        
    } catch (const std::exception& e) {
        std::cerr << "Error parsing record: " << e.what() << std::endl;
        record.valid = false;
    }
    
    return record;
}

uint8_t HexParser::calculateChecksum(const HexRecord& record) {
    uint8_t checksum = record.length;
    checksum += (record.address >> 8) & 0xFF;
    checksum += record.address & 0xFF;
    checksum += static_cast<uint8_t>(record.type);
    
    for (uint8_t byte : record.data) {
        checksum += byte;
    }
    
    return (~checksum + 1) & 0xFF;
}

bool HexParser::validateChecksum(const HexRecord& record) {
    return calculateChecksum(record) == record.checksum;
}

std::vector<uint8_t> HexParser::hexStringToBytes(const std::string& hex) {
    std::vector<uint8_t> bytes;
    
    for (size_t i = 0; i < hex.length(); i += 2) {
        if (i + 1 < hex.length()) {
            std::string byte_str = hex.substr(i, 2);
            uint8_t byte = static_cast<uint8_t>(hexStringToNumber(byte_str));
            bytes.push_back(byte);
        }
    }
    
    return bytes;
}

uint32_t HexParser::hexStringToNumber(const std::string& hex) {
    return static_cast<uint32_t>(std::stoul(hex, nullptr, 16));
}

const HexFileInfo& HexParser::getFileInfo() const {
    return file_info;
}

void HexParser::printFileInfo() const {
    std::cout << "\n=== HEX File Information ===" << std::endl;
    std::cout << "Filename: " << file_info.filename << std::endl;
    std::cout << "Total records: " << file_info.total_records << std::endl;
    std::cout << "Data records: " << file_info.data_records << std::endl;
    std::cout << "Total data bytes: " << file_info.total_data_bytes << " bytes" << std::endl;
    std::cout << "Program entry point: 0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << file_info.start_address << std::endl;
    std::cout << "End address: 0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << file_info.end_address << std::endl;
    std::cout << "Extended linear address: 0x" << std::hex << std::uppercase << file_info.extended_linear_address << std::endl;
    std::cout << "Extended segment address: 0x" << std::hex << std::uppercase << file_info.extended_segment_address << std::endl;
    std::cout << "Memory map size: " << std::dec << file_info.memory_map.size() << " bytes" << std::endl;
    
    // 显示记录类型统计
    std::map<HexRecordType, int> type_count;
    for (const auto& record : file_info.records) {
        type_count[record.type]++;
    }
    
    std::cout << "\nRecord type statistics:" << std::endl;
    for (const auto& pair : type_count) {
        std::string type_name;
        switch (pair.first) {
            case HexRecordType::DATA: type_name = "Data record"; break;
            case HexRecordType::END_OF_FILE: type_name = "End of file"; break;
            case HexRecordType::EXTENDED_SEGMENT_ADDRESS: type_name = "Extended segment address"; break;
            case HexRecordType::START_SEGMENT_ADDRESS: type_name = "Start segment address"; break;
            case HexRecordType::EXTENDED_LINEAR_ADDRESS: type_name = "Extended linear address"; break;
            case HexRecordType::START_LINEAR_ADDRESS: type_name = "Start linear address"; break;
            default: type_name = "Unknown type"; break;
        }
        std::cout << "  " << type_name << ": " << pair.second << " records" << std::endl;
    }
}

void HexParser::printMemoryMap() const {
    std::cout << "\n=== Memory Map (first 256 bytes) ===" << std::endl;
    
    auto it = file_info.memory_map.begin();
    int count = 0;
    
    while (it != file_info.memory_map.end() && count < 256) {
        std::cout << "Address 0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(8) 
                  << it->first << ": 0x" << std::setw(2) << static_cast<int>(it->second) << std::endl;
        ++it;
        ++count;
    }
    
    if (file_info.memory_map.size() > 256) {
        std::cout << "... (" << (file_info.memory_map.size() - 256) << " more bytes not shown)" << std::endl;
    }
}

bool HexParser::validateFile() const {
    bool has_end_record = false;
    bool has_data = false;
    
    for (const auto& record : file_info.records) {
        if (!record.valid) {
            std::cerr << "Found invalid record" << std::endl;
            return false;
        }
        
        if (record.type == HexRecordType::END_OF_FILE) {
            has_end_record = true;
        }
        
        if (record.type == HexRecordType::DATA && !record.data.empty()) {
            has_data = true;
        }
    }
    
    if (!has_data) {
        std::cerr << "Warning: No data records found in file" << std::endl;
    }
    
    if (!has_end_record) {
        std::cerr << "Warning: No end of file record found" << std::endl;
    }
    
    return true;
}

std::vector<uint8_t> HexParser::getDataAtAddress(uint32_t address, size_t length) const {
    std::vector<uint8_t> result;
    
    for (size_t i = 0; i < length; ++i) {
        auto it = file_info.memory_map.find(address + i);
        if (it != file_info.memory_map.end()) {
            result.push_back(it->second);
        } else {
            result.push_back(0xFF); // 默认填充值
        }
    }
    
    return result;
}

const std::vector<HexRecord>& HexParser::getDataRecords() const {
    return file_info.records;
}

void HexParser::analyzeSegments() {
    file_info.segments.clear();
    
    if (file_info.memory_map.empty()) {
        return;
    }
    
    // 按地址排序找到连续的段
    std::vector<std::pair<uint32_t, uint8_t>> sorted_data;
    for (const auto& pair : file_info.memory_map) {
        sorted_data.push_back(pair);
    }
    std::sort(sorted_data.begin(), sorted_data.end());
    
    if (sorted_data.empty()) return;
    
    SegmentInfo current_segment;
    current_segment.start_address = sorted_data[0].first;
    current_segment.data.push_back(sorted_data[0].second);
    
    for (size_t i = 1; i < sorted_data.size(); ++i) {
        uint32_t current_addr = sorted_data[i].first;
        uint32_t prev_addr = sorted_data[i-1].first;
        
        // 检查是否连续（允许小的间隔）
        if (current_addr - prev_addr <= 1) {
            // 连续或相邻，添加到当前段
            current_segment.data.push_back(sorted_data[i].second);
        } else {
            // 不连续，结束当前段，开始新段
            current_segment.end_address = prev_addr;
            current_segment.data_size = current_segment.data.size();
            file_info.segments.push_back(current_segment);
            
            // 开始新段
            current_segment = SegmentInfo();
            current_segment.start_address = current_addr;
            current_segment.data.clear();
            current_segment.data.push_back(sorted_data[i].second);
        }
    }
    
    // 添加最后一个段
    current_segment.end_address = sorted_data.back().first;
    current_segment.data_size = current_segment.data.size();
    file_info.segments.push_back(current_segment);
}

void HexParser::printSegmentInfo() const {
    std::cout << "\n=== Segment Information ===" << std::endl;
    
    for (size_t i = 0; i < file_info.segments.size(); ++i) {
        const auto& segment = file_info.segments[i];
        std::cout << "Segment " << i << ":" << std::endl;
        std::cout << "  Start address: 0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << segment.start_address << std::endl;
        std::cout << "  End address: 0x" << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << segment.end_address << std::endl;
        std::cout << "  Size: " << std::dec << segment.data_size << " bytes" << std::endl;
        
        // 显示前16字节数据
        std::cout << "  First 16 bytes: ";
        for (size_t j = 0; j < std::min(segment.data.size(), size_t(16)); ++j) {
            std::cout << std::hex << std::uppercase << std::setfill('0') << std::setw(2) 
                      << static_cast<int>(segment.data[j]) << " ";
        }
        std::cout << std::endl;
    }
}
